//============================================================================================
/**
 * @file	startmenu.c
 * @brief	タイトルメニュー
 * @author	Satoshi Mitsuhara
 * @date	06.04.11
 *
 * $Id: startmenu.c,v 1.72 2007/02/09 09:54:58 matsuda Exp $
 */
//============================================================================================
#include "common.h"
#include "system/procsys.h"
#include "system/main.h"
#include "system/wipe.h"
#include "system/wordset.h"
#include "system/msgdata_util.h"
#include "system/arc_util.h"
#include "system/window.h"
#include "system/snd_tool.h"
#include "system/snd_play.h"
#include "system/render_oam.h"

#include "gflib/bg_system.h"
#include "gflib/rebooter.h"
#include "gflib/touchpanel.h"

#include "savedata/savedata.h"
#include "savedata/zukanwork.h"
#include "savedata/playtime.h"
#include "savedata/fushigi_data.h"
#include "savedata/system_data.h"

#include "msgdata/msg.naix"
#include "msgdata/msg_startmenu.h"
#include "msgdata/msg_bconfind.h"

#include "communication/comm_state.h"

#include "../fushigi/agbpoke_access.h"
#include "../fushigi/mysterylib.h"
#include "../fushigi/agbdownload.h"
#include "../fushigi/mystery.naix"

#include "msgdata/msg_wifi_system.h"
#include "wifi/dwc_rap.h"

#include "application/backup.h"

/*
 * ※必ず表示されるメニュー
 *
 *	つづきからはじめる
 *	さいしょからはじめる
 *	WiFiせってい
 *
 * ※カートリッジが刺さっていると表示されるメニュー
 *
 *	なんとかとからつれてくる(ルビー/サファイア/...)
 *
 * ※条件によって表示されるメニュー
 *
 *	ポケモンレンジャーとせつぞく
 *	Wiiとのせつぞく
 *
 * ※メニューから選択した後に接続するもの
 *
 *	ダイレクトせつぞく
 *	WiFiせつぞく
 *	ビーコンせつぞく
 *
 */
/*
	タイトルメニューの最初の時点でお願いしたい事があります。
	WIFIの初期化関数なのですが、この関数の戻り値が
	DWC_INIT_RESULT_DESTROY_OTHER_SETTING　の場合に、
	メッセージを出していただきたいのです。
	ちなみにこのエラーはDS本体の通信情報が壊れた場合に出ます。

	#include "msgdata/msg_wifi_system.h"
	#include "wifi/dwc_rap.h"

	ret = mydwc_init(HEAPID_BASE_APP);
	if(ret == DWC_INIT_RESULT_DESTROY_OTHER_SETTING){
		message (	dwc_message_0001 );
	}

	PAD_BUTTON_DECIDE|PAD_BUTTON_CANCEL で本物のタイトルへ移動

	こういった流れになります。
*/

//
// BG0 - メニュー表示画面
// BG1 - ビーコンを拾った際に表示されるメニュー(一時的表示のみ)
// BG2 - 通信アイコン(BG0と一緒にスクロール)
//

#define WIICLIENT_FILE		"data/eoo.dat"

// メニューのXキャラ幅
#define MENU_WIDTH	(23)
#define MENU_HEIGHT0	(10)
#define MENU_HEIGHT1	(4)
#define MENU_XOFS		(3)
#define MENU_AREA_SX	(MENU_XOFS*8-4)
#define MENU_AREA_EX	((MENU_XOFS+MENU_WIDTH)*8+4)

//ビーコン関連ウィンドウ定義
#define BCMSG_PX	(4)
#define BCMSG07_PY	(14)
#define BCMSG08_PY	(19)
#define BCMSG_BTN_SX	(24)
#define BCMSG_BTN_SY	(3)

//ビーコン検出時キーフックウェイト
#define BEACON_KEY_WAIT			(30)	//その他
#define BEACON_KEY_WAIT_FMSG	(30)		//NewGame時警告

#define STARTMENU_FCHR1		(1024-MENU_WIN_CGX_SIZ)			// 通常フレーム
#define STARTMENU_FCOL1		2
#define STARTMENU_FCHR2		(STARTMENU_FCHR1 - MENU_WIN_CGX_SIZ)	// 選択時フレーム
#define STARTMENU_FCOL2		3

#define WIRELESS_CHR_SIZ		(4*2)
#define WIRELESS_CHR_BASE		(STARTMENU_FCHR2-WIRELESS_CHR_SIZ)
#define WIRELESS_ICON_BASE		((STARTMENU_WICON_PAL << 12) + WIRELESS_CHR_BASE + 0)

//通常メニューウィンドウ領域
#define STARTMENU_WCHR		(1)

//最初から始めるを選択した後にでる選択肢2つ分(冒険を始める、メニューに戻る)
#define STARTMENU_NGAME_WCHR_ONE_SIZ	(BCMSG_BTN_SX*3)
#define STARTMENU_NGAME_WCHR_SIZ	(STARTMENU_NGAME_WCHR_ONE_SIZ*2)
#define STARTMENU_NGAME_WCHR	(1)

//ビーコン説明ウィンドウ用領域
#define BEACON_MSG_WCHR	(STARTMENU_NGAME_WCHR+STARTMENU_NGAME_WCHR_SIZ)

#define STARTMENU_WCOL_SELECT	0
#define STARTMENU_WCOL_NORMAL	1

#define STARTMENU_WICON_PAL	4

#define STARTMENU_NOSELECT	-1

#define STARTMENU_FIRSTGAME_SELECT	0x80

//1ライン(一項目)のY幅
#define LINE_HEIGHT		(6*8)
#define LINE_HEIGHT_FX	(FX32_CONST(LINE_HEIGHT))

//各ページのスクロール座標Y
#define SCR_TARGET_PAGE0	(0)
#define SCR_TARGET_PAGE1	(FX32_CONST(192))
#define SCR_TARGET_PAGE2	(FX32_CONST(384))

//各ページのスタートIndex
#define PAGE0_START	(0)
#define PAGE1_START	(3)
#define PAGE2_START	(7)

#define RGB(r, g, b)	(((b)&31)<<10|((g)&31)<<5|((r)&31))

//入力実行コード
enum{
 MENU_EXE_DECIDE,
 MENU_EXE_CANCEL,
};

enum {
	// メインシーケンス
	STARTMENU_SEQ_INIT,
	STARTMENU_SEQ_CHECK_SYSTEM,		// 各種システムチェック
	STARTMENU_SEQ_DISP_ERROR,
	STARTMENU_SEQ_HARDINIT,
	STARTMENU_SEQ_CREATE_SCREEN,		// スクリーン作成(基本形)
	STARTMENU_SEQ_MAIN,
	STARTMENU_SEQ_SELECT_FIRSTGAME,

	STARTMENU_SEQ_SELECT_MENU,		// メニューが選択された後の処理

	STARTMENU_SEQ_FADE_WAIT,
	STARTMENU_SEQ_FINISH,			// 何もせず抜ける

	// ビーコン取得シーケンス
	STARTMENU_BEACON_SEQ_INIT,		// 初期化
	STARTMENU_BEACON_SEQ_INIT2,		// 初期化
	STARTMENU_BEACON_SEQ_WAIT,		// メイン処理が良いというまで待つ
	STARTMENU_BEACON_SEQ_TIMER,		// 実際のビーコン収集処理
	STARTMENU_BEACON_SEQ_CANCEL,		// 強制キャンセルモード

	// ビーコン取得時のメッセージ表示
	BEACON_MSGSEQ_NOP,			// 何もしない
	BEACON_MSGSEQ_INIT,			// 初期化
	BEACON_MSGSEQ_INIT_DISP,		// スクリーン初期化
	BEACON_MSGSEQ_INIT_MAIN,		// キー入力待ち
	BEACON_MSGSEQ_INIT_MAIN_FMSG,	// キー入力待ち
	BEACON_MSGSEQ_INIT_FINISH,		// 終了
	BEACON_MSGSEQ_FADE_WAIT,		// フェード待ち

	STARTMENU_SEQ_MAX
};


typedef struct _STARTMENU_DATA {
	int mark;
	int height;
	int msgid;
	// 表示時に呼び出されるファンクション
	BOOL (*func)(void* /* STARTMENU_WORK */, int, MYSTERY_WIN *, int);
} STARTMENU_DATA;


static BOOL StartMenuAgbPokemon(void *p, int index, MYSTERY_WIN *, int y);
static BOOL StartMenuCheckMystery(void *p, int index, MYSTERY_WIN *, int y);
static BOOL StartMenuCheckRanger(void *p, int index, MYSTERY_WIN *, int y);
static BOOL StartMenuCheckWii(void *p, int index, MYSTERY_WIN *, int y);
static BOOL StartMenuSetWifi(void *p, int index, MYSTERY_WIN *, int y);
static BOOL StartMenuSetPHC(void *p, int index, MYSTERY_WIN *mw, int y);
static BOOL StartMenuSetEmail(void *p, int index, MYSTERY_WIN *mw, int y);
static BOOL StartMenuContinue(void *p, int index, MYSTERY_WIN *, int y);

enum {
	SEL_CANCEL = 0,
	SEL_CONTINUE,
	SEL_FIRSTGAME,
	SEL_PHC,
	SEL_MYSTERY,
	SEL_RANGER,
	SEL_AGBPOKEMON,
	SEL_WII,
	SEL_WIFI,
	SEL_EMAIL,
	SEL_MAX,
};

enum {
	STARTMENU_DWC_ERROR = 0,		// DS本体の通信情報が壊れている
	STARTMENU_ERROR_MAX
};

typedef struct {
	int sx, sy, width, height;
	u32 arc, msgid;
	void (*func)(void* /*STARTMENU_WORK* */);
} ERRORTABLE;

// ２つセットのエラー表示メッセージ
static ERRORTABLE ErrorMsgTable[] = {
	{ 5, 5, 22, 14, NARC_msg_wifi_system_dat, dwc_message_0001, NULL/*DispErrorDwc*/ },
};


STARTMENU_DATA StartMenuWinTable[] = {
 // つづきから はじめる
 { SEL_CONTINUE, MENU_HEIGHT0, mes_startmenu_continue,	StartMenuContinue },
 // さいしょから　はじめる
 { SEL_FIRSTGAME, MENU_HEIGHT1, mes_startmenu_newgame,	NULL },
 // PHC
 { SEL_PHC, MENU_HEIGHT1, mes_startmenu_phc, 	StartMenuSetPHC },
 // ふしぎな　おくりもの
 { SEL_MYSTERY, MENU_HEIGHT1, mes_startmenu_mystery,	StartMenuCheckMystery },
 // ポケモンレンジャーとの　せつぞく
 { SEL_RANGER, MENU_HEIGHT1, mes_startmenu_ranger, 	StartMenuCheckRanger },
 // ×××から　つれてくる
 { SEL_AGBPOKEMON, MENU_HEIGHT1, NULL, 			StartMenuAgbPokemon },
 // Wiiと　せつぞく
 { SEL_WII, MENU_HEIGHT1, mes_startmenu_wii, 	StartMenuCheckWii },
 // Wi-Fiせってい
 { SEL_WIFI, MENU_HEIGHT1, mes_startmenu_wifi, 	StartMenuSetWifi },
 // E-MAIL
 { SEL_EMAIL, MENU_HEIGHT1, mes_startmenu_email, 	StartMenuSetEmail },
};


static u32 StartMenuContinueTable[] = {
	mes_startmenu_continue,			// つづきから　はじめる
	mes_startmenu_13,			// しゅじんこう
	mes_startmenu_14,			// プレイじかん
	mes_startmenu_16,			// もっているバッジ
	mes_startmenu_15,			// ポケモンずかん
};

// ビーコンを拾ったときのメッセージデータ
typedef struct {
	int sx, sy;
	int width, height;
	int msg;
} BEACON_MSG_TABLE;

BEACON_MSG_TABLE BeaconMsgTable[] = {
	{ BCMSG_PX, 2, 24, 20, bcon_002 },		// ふしぎなおくりものを発見。メニューで選んでね
	{ BCMSG_PX, 4, 24, 16, bcon_004 },		// ふしぎなおくりものを発見。でもまだダメ
	{ BCMSG_PX, 1, 24, 22, bcon_001 },		// レンジャーを発見。メニューで選んでね
	{ BCMSG_PX, 3, 24, 18, bcon_003 },		// レンジャーを発見。でもまだダメ
	// ↓これだけメニュー選択時メッセージ
	{ 0, 1, 32, 11, bcon_006 },		// さいしょからはじめてもセーブできんよ？
	{ BCMSG_PX, BCMSG07_PY, BCMSG_BTN_SX, BCMSG_BTN_SY, bcon_007 },		// さいしょからはじめてもセーブできんよ？
	{ BCMSG_PX, BCMSG08_PY, BCMSG_BTN_SX, BCMSG_BTN_SY, bcon_008 },		// さいしょからはじめてもセーブできんよ？
};



// メニューの最大数
#define MENU_WIN_MAX	(sizeof(StartMenuWinTable) / sizeof(STARTMENU_DATA))

#define	NEXT_TOUCH_SCROLL_WAIT	( 6 )	// 次のタッチスクロールが有効になるまでのウェイト

// ビーコン情報を集める時間
#define BEACON_GATHER_TIME	(2*60)

#define SetSeq(w, n)	(w = n)


typedef struct {
	GF_BGL_INI *bgl;
	SAVEDATA *sv;
	ZUKAN_WORK *zw;
	MYSTATUS *mst;
	PLAYTIME *ptime;
	FUSHIGI_DATA *fdata;			// ふしぎデータを読んだ場所

	// メインシーケンス関係

	int jiffy;
	int next_seq;
	int chrbase;				// ウィンドウのキャラクタベース
	int agbpokemon;				// 刺さっているAGBカセットのタイプ(CASTYPE_xxx)
	int agbpokemoncheck;
	int pokemonranger;			// ポケモンレンジャーを発見した
	int wii;					// Wiiのビーコンを発見した
	int mystery;				// ふしぎな　おくりものビーコン

	int menu_flag;				// 各種ビーコンメニューを表示したか？(PARTYGAME_xxx)
	int new_menu_flag;


	int beacon_status;
	int beacon_disp_status;
	int redrawflag;

	int zukangetflag;			// ずかんを持っているならTRUE
	int badgecount;			// もっているバッチの数


	u16 cursor;				// 現在のカーソル位置
	u16 cursor_ng;			// 現在のカーソル位置NewGame選択画面

	int select;				// 選択された項目(-1ならば何も選択していない)

	GF_BGL_BMPWIN mwin[MENU_WIN_MAX];
	int menuflag[MENU_WIN_MAX];		// 表示されていたらTRUE(default = FALSE)
	int iconflag[MENU_WIN_MAX];		// ワイヤレスアイコンがある時にTRUE

	fx32 scrolly;				// 現在のスクロール値
	fx32 target;				// 目的座標

	// ビーコン取得関係
	int beacon_seq;
	int beacon_wait;
	int beacon_msg_seq;			// ビーコン取得時に表示するメッセージシーケンス
	int beacon_msg_wait;
	int beacon_key_wait;
	int beacon_result;
	GF_BGL_BMPWIN beacon_win;
	GF_BGL_BMPWIN beacon_win_sub[2];

	int pass_start_menu;			// TRUEならばスタートメニューを表示させない
	int req_popup;

	// エラー情報
	BOOL errorflag[STARTMENU_ERROR_MAX];
	GF_BGL_BMPWIN ewin;

	// カーソルアクター
	CLACT_WORK_PTR clcursor[2];		// 0 = ↑　1 = ↓

	int anim_index;
	int	key_mode;	///<キー/タッチモード
	int	list_max;	///<有効なメニュー数

	int	touch_wait;	///<矢印タッチでスクロールするときに、次の入力が有効になるためのウェイト
} STARTMENU_WORK;






//============================================================================================
//	外部関数定義
//============================================================================================
extern FUSHIGI_DATA * SaveData_GetFushigiData(SAVEDATA * sv);
extern int CommPlayerNowFlagDataArraySize(void);
extern int MyStatus_GetWorkSize(void);
extern void CreateIndexData(int heapid);

//============================================================================================
//	プロトタイプ定義
//============================================================================================
static void RedrawWindowFrame(STARTMENU_WORK *wk, int select);
static void RedrawWindowFrameNewGame(STARTMENU_WORK *wk, int select);
static void SelectPalAnim(STARTMENU_WORK *wk);
static BOOL NextCursorPosition(STARTMENU_WORK *wk, int offset);
static void SetCursorScroll(STARTMENU_WORK *wk,int pos);
static void SetCursorVisible(STARTMENU_WORK *wk);

//============================================================================================
//	定数定義
//============================================================================================
#define ACT_AL_OX	(256-20)
#define ACT_AL_OY0	(20)
#define ACT_AL_OY1	(192-20)
#define TP_AL_SX	(28)
#define TP_AL_SY	(28)
#define TP_AL_PX	(ACT_AL_OX-(TP_AL_SX/2))

#define TP_ALU_PY	(ACT_AL_OY0-(TP_AL_SY/2))
#define TP_ALD_PY	(ACT_AL_OY1-(TP_AL_SY/2))

#define TP_BCBTN_PX	(BCMSG_PX*8)
#define TP_BCBTN_PY01	(BCMSG07_PY*8)
#define TP_BCBTN_PY02	(BCMSG08_PY*8)
#define TP_BCBTN_SX		(BCMSG_BTN_SX*8)
#define TP_BCBTN_SY		(BCMSG_BTN_SY*8)

/**
 *	@brief	キー/タッチ切替チェック
 */
static int KeyTouchChange(STARTMENU_WORK* wk,u8 mode)
{
	if(wk->key_mode == APP_KTST_KEY){
		if(sys.trg){
			return 0;
		}
		if(GF_TP_GetTrg()){
			wk->key_mode = APP_KTST_TOUCH;
			//コールバック
			if(mode == 0){
				RedrawWindowFrame(wk, 0xFF);
			}else{
				RedrawWindowFrameNewGame(wk, 0xFF);
			}
			return 0;
		}
	}else{
		if(GF_TP_GetCont()){
			return 0;
		}
		if(sys.trg){
			wk->key_mode = APP_KTST_KEY;
			//コールバック
			if(mode == 0){
				RedrawWindowFrame(wk, wk->cursor);
			}else{
				RedrawWindowFrameNewGame(wk, wk->cursor_ng);
			}
			return 1;
		}
	}
	return 0;
}

/**
 *	@brief	キー/タッチinputチェック A/Bのみ
 */
static int InputCheck(STARTMENU_WORK* wk)
{
	int ret;
	u16	pat,line;

	if(sys.trg & PAD_BUTTON_KTST_CHG){
		wk->key_mode = APP_KTST_KEY;
		return sys.trg;
	}
	if(GF_TP_GetTrg()){
		wk->key_mode = APP_KTST_TOUCH;
		return PAD_BUTTON_DECIDE;
	}
	return 0;
}

/**
 *	@brief	先頭からX番目に有効なカーソル位置を取得
 */
static int GetValidCursorPos(STARTMENU_WORK* wk,u8 idx)
{
	int i,ct;

	for(i = 0,ct = 0;i < MENU_WIN_MAX;i++){
		if(!wk->menuflag[i]){
			continue;
		}
		if(ct++ == idx){
			return i;
		}
	}
	//ここには来るべきじゃない
	return 0;
}

/**
 *	@brief	メニュー入力実行
 */
static int InputCheckMenuExe(STARTMENU_WORK* wk,int* seq,int code)
{
	if(code == MENU_EXE_DECIDE){
		Snd_SePlay(SEQ_SE_DP_SELECT);
		wk->select = wk->menuflag[wk->cursor];

		// AGBカセットから連れてくるを選んだ際の停止判定処理
		if(wk->select == SEL_AGBPOKEMON){
			// カセットが抜かれていたらエラー画面へ飛ぶ
			if(CTRDG_IsPulledOut() == TRUE){
				if(wk->beacon_seq != STARTMENU_BEACON_SEQ_WAIT){
					CommStateExitPartyGameScan();
				}
				GbaCartridgeErrorWarningCall(HEAPID_STARTMENU);
			}
		}
	}else{	//CANCEL
		Snd_SePlay(SEQ_SE_DP_SELECT);
		wk->select = SEL_CANCEL;
		MysteryLib_ChangeFadeType(1);
	}

	if(wk->select == SEL_FIRSTGAME){
		// さいしょからはじめるを選択した場合には警告画面を表示する
		wk->beacon_status |= STARTMENU_FIRSTGAME_SELECT;
		wk->beacon_msg_wait = 1;
		SetSeq(*seq, STARTMENU_SEQ_SELECT_FIRSTGAME);
	}else{
		if(wk->select == SEL_WII){
			MysteryLib_ChangeFadeType(1);
		}
		MysteryLib_RequestFade(WIPE_TYPE_FADEOUT, STARTMENU_SEQ_SELECT_MENU, seq, STARTMENU_SEQ_FADE_WAIT);
	}

	// ビーコン収集中だったら強制終了処理へ
	if(wk->beacon_seq == STARTMENU_BEACON_SEQ_TIMER){
		wk->beacon_seq = STARTMENU_BEACON_SEQ_CANCEL;
	}
	return TRUE;
}

// メニューインデックスからカーソル位置取得
static int MenuIndexPosGet( STARTMENU_WORK * wk, int index )
{
	int	i, j;

	j = 0;
	for( i=0; i<index; i++ ){
		if( wk->menuflag[i] != 0 ){
			j++;
		}
	}
	return j;
}

/**
 *	@brief	メニューキーチェック
 */
static int InputCheckMenuKey(STARTMENU_WORK* wk,int* seq)
{
	int scr_f = FALSE,old,pos;

	if((sys.trg & PAD_BUTTON_KTST_CHG) && (wk->key_mode == APP_KTST_TOUCH)){
		wk->key_mode = APP_KTST_KEY;
		RedrawWindowFrame(wk, wk->cursor);
		return FALSE;
	}

	if(sys.trg & PAD_BUTTON_DECIDE){
		return InputCheckMenuExe(wk,seq,MENU_EXE_DECIDE);
	}else if(sys.trg & PAD_BUTTON_CANCEL){
		return InputCheckMenuExe(wk,seq,MENU_EXE_CANCEL);
	}
	if(wk->redrawflag){
		return 0;
	}
	old = wk->cursor;
	if(sys.trg & PAD_KEY_UP){
		if(NextCursorPosition(wk, -1)){
			pos = MenuIndexPosGet( wk, old );
//			if(old == PAGE2_START){
			if(pos == PAGE2_START){
				pos = PAGE1_START;
				scr_f = TRUE;
//			}else if(old == PAGE1_START){
			}else if(pos == PAGE1_START){
				pos = PAGE0_START;
				scr_f = TRUE;
			}
		}
	}else if(sys.trg  & PAD_KEY_DOWN){
		scr_f = NextCursorPosition(wk, 1);
		pos = wk->cursor;
	}
	if(scr_f){
		// スクロール処理
		SetCursorScroll(wk,pos);
	}
	return 0;
}

/**
 *	@brief	メニュータッチチェック
 */
static int InputCheckMenuTouch(STARTMENU_WORK* wk,int* seq,BOOL* touch_f)
{
	int ret = RECT_HIT_NONE,scr_f = FALSE;
	u16	pat,line;

	static const RECT_HIT_TBL Allow_TpRect[] = {
//		{0,191,0,255}, ty,by,lx,rx
		{TP_ALU_PY,TP_ALU_PY+TP_AL_SY,TP_AL_PX,TP_AL_PX+TP_AL_SX},
		{TP_ALD_PY,TP_ALD_PY+TP_AL_SY,TP_AL_PX,TP_AL_PX+TP_AL_SX},
		{RECT_HIT_END,0,0,0}
	};

	if(!GF_TP_GetTrg()){
		return 0;
	}
	//スクロールボタン HIT取得
	if(wk->redrawflag == FALSE){
		if( wk->touch_wait == 0 ){
			ret = GF_TP_RectHitTrg(Allow_TpRect);
		}else{
			ret = RECT_HIT_NONE;
		}
	}
	if(ret == 0 && (CLACT_AnmGet(wk->clcursor[0])/2)){
		CLACT_SetAnmFlag(wk->clcursor[0], TRUE);
		CLACT_AnmReStart(wk->clcursor[0]);
		if(wk->cursor > PAGE1_START && wk->target > SCR_TARGET_PAGE1){
			wk->cursor = GetValidCursorPos(wk,PAGE1_START);
		}else{
			wk->cursor = GetValidCursorPos(wk,PAGE0_START);
		}
		*touch_f = TRUE;
		OS_Printf("up target = %d,%x\n",wk->target/FX32_ONE,wk->target);
		scr_f  = TRUE;
	}else if(ret == 1 && (CLACT_AnmGet(wk->clcursor[1])/2)){
		CLACT_SetAnmFlag(wk->clcursor[1], TRUE);
		CLACT_AnmReStart(wk->clcursor[1]);
		if(wk->cursor < PAGE1_START){
			wk->cursor = GetValidCursorPos(wk,PAGE1_START);
		}else{
			wk->cursor = GetValidCursorPos(wk,PAGE2_START);
		}
		*touch_f = TRUE;
		OS_Printf("dw target = %d,%x\n",wk->target/FX32_ONE,wk->target);
		scr_f  = TRUE;

	}
	if(scr_f){
		// スクロール処理
		wk->key_mode = APP_KTST_TOUCH;
		RedrawWindowFrame(wk, wk->cursor);
		SetCursorScroll(wk,wk->cursor);
		wk->touch_wait = NEXT_TOUCH_SCROLL_WAIT;
		return FALSE;
	}
	{
		u16	py;
		u16 pat = 0xfffe;	//1111 1111 1111 1110	無効パレットbit(onになっている色No以外は反応させない)

		py = sys.tp_y + (wk->target/FX32_ONE);
		if(py >= 512){	//領域外
			return FALSE;
		}
		if(GF_BGL_DotCheck(wk->bgl,GF_BGL_FRAME0_M,sys.tp_x,py,&pat) == FALSE){
			return FALSE;
		}
	}
	*touch_f = TRUE;

	line = sys.tp_y/(LINE_HEIGHT);
	if(wk->target == SCR_TARGET_PAGE0){
		if(line > 0){	//Page1
			--line;
		}
	}else if(wk->target == SCR_TARGET_PAGE1){	//Page2,3
		line += PAGE1_START;
	}else{
		line += PAGE2_START;
	}
	if(line >= wk->list_max){
		return FALSE;
	}
	wk->cursor = GetValidCursorPos(wk,line);
	wk->key_mode = APP_KTST_TOUCH;
	RedrawWindowFrame(wk, wk->cursor);
	return InputCheckMenuExe(wk,seq,MENU_EXE_DECIDE);
}


/**
 *	@brief	キー/タッチinputチェック
 */
static int InputCheckMenu(STARTMENU_WORK* wk,int* seq)
{
	int ret,touch_f = FALSE;

	ret = InputCheckMenuTouch(wk,seq,&touch_f);

	if(touch_f){
		wk->key_mode = APP_KTST_TOUCH;
		// 矢印がタッチされた直後は描画する必要がない
		if( wk->touch_wait != NEXT_TOUCH_SCROLL_WAIT ){
			RedrawWindowFrame(wk, 0xFF);
		}
		return ret;
	}
	return InputCheckMenuKey(wk,seq);
}

/**
 *	@brief	NewGame警告画面　タッチ入力
 */
static int InputCheckNewGameTouch(STARTMENU_WORK* wk,BOOL* touch_f)
{
	int ret;
	u16	pat,line;

	static const RECT_HIT_TBL Btn_TpRect[] = {
//		{0,191,0,255}, ty,by,lx,rx
		{TP_BCBTN_PY01,TP_BCBTN_PY01+TP_BCBTN_SY,TP_BCBTN_PX,TP_BCBTN_PX+TP_BCBTN_SX},
		{TP_BCBTN_PY02,TP_BCBTN_PY02+TP_BCBTN_SY,TP_BCBTN_PX,TP_BCBTN_PX+TP_BCBTN_SX},
		{RECT_HIT_END,0,0,0}
	};

	if(!GF_TP_GetTrg()){
		return 0;
	}
	//スクロールボタン HIT取得
	ret = GF_TP_RectHitTrg(Btn_TpRect);
	if(ret == RECT_HIT_NONE){
		return 0;
	}
	pat = 0xfffe;	//1111 1111 1111 1110	無効パレットbit(onになっている色No以外は反応させない)
	if(GF_BGL_DotCheck(wk->bgl,GF_BGL_FRAME1_M,sys.tp_x,sys.tp_y,&pat) == FALSE){
		return 0;
	}
	*touch_f = TRUE;
	if(ret == 0){
		return PAD_BUTTON_DECIDE;
	}
	return PAD_BUTTON_CANCEL;
}

/**
 *	@brief	キー/タッチinputチェック(NewGame警告面)
 */
static int InputCheckNewGame(STARTMENU_WORK* wk)
{
	BOOL touch_f = FALSE;
	int ret;

	ret = InputCheckNewGameTouch(wk,&touch_f);
	if(touch_f){
		wk->key_mode = APP_KTST_TOUCH;
		RedrawWindowFrameNewGame(wk, 0xFF);
		return ret;
	}
	if(!sys.trg){
		return 0;
	}

	if(sys.trg & PAD_BUTTON_KTST_CHG && wk->key_mode == APP_KTST_TOUCH){
		wk->key_mode = APP_KTST_KEY;
		RedrawWindowFrameNewGame(wk, wk->cursor_ng);
		return 0;
	}
	if(sys.trg & (PAD_KEY_UP|PAD_KEY_DOWN)){
		wk->cursor_ng ^= 1;
		RedrawWindowFrameNewGame(wk, wk->cursor_ng);
		Snd_SePlay(SEQ_SE_DP_SELECT);
		return 0;
	}
	if(sys.trg & PAD_BUTTON_DECIDE){
		if(wk->cursor_ng == 0){
			return PAD_BUTTON_DECIDE;
		}else{
			return PAD_BUTTON_CANCEL;
		}
	}
	if(sys.trg & PAD_BUTTON_CANCEL){
		return PAD_BUTTON_CANCEL;
	}
	return 0;
}

//------------------------------------------------------------------
/**
 * @brief	システムエラーチェック
 * @param	NONE
 * @return	NONE
 *
 * mainで呼ばれるようになったので、この関数は無効
 */
//------------------------------------------------------------------
static int StartMenuCheckSystem(STARTMENU_WORK *wk)
{
	int max, ret;

	max = 0;
	return max;
}


//------------------------------------------------------------------
/**
 * @brief	エラー情報を表示する
 * @param	NONE
 * @return	NONE
 */
//------------------------------------------------------------------
static BOOL StartMenuDisplayError(STARTMENU_WORK *wk)
{
	int i;
	ERRORTABLE *et;
	MYSTERY_WIN mw;

	// エラー表示ウィンドウが初期化されているかどうかで判断を行おうかな
	if(GF_BGL_BmpWinAddCheck(&wk->ewin) == FALSE){
		for(i = 0; i < STARTMENU_ERROR_MAX; i++){
			if(wk->errorflag[i] == TRUE){
				wk->errorflag[i] = FALSE;
				et = &ErrorMsgTable[i];
				//ここでエラー表示を行う
				MysteryLib_WinInit1(&mw, &wk->ewin,
					STARTMENU_WCOL_SELECT, et->arc, STARTMENU_FCHR1, STARTMENU_FCOL1);
				MysteryLib_WinInit2(&mw, et->width, et->height, /*et->msgid,*/ STARTMENU_WCHR);
				MysteryLib_CreateWin(wk->bgl, &mw, et->sx, et->sy, et->msgid);
				return TRUE;
			}
		}
	}else{
		// エラーウィンドウの表示中
		if(InputCheck(wk) & (PAD_BUTTON_DECIDE|PAD_BUTTON_CANCEL)){
			Snd_SePlay(SEQ_SE_DP_SELECT);
			BmpMenuWinClear(&wk->ewin, WINDOW_TRANS_ON);
			GF_BGL_BmpWinDel(&wk->ewin);
		}
		return TRUE;
	}
	return FALSE;
}


//------------------------------------------------------------------
/**
 * @brief	ＡＧＢカセットが刺さっているか初期化する
 * @param	NONE
 * @return	NONE
 */
//------------------------------------------------------------------
static void AgbCartridgeInit(STARTMENU_WORK *wk)
{
	int pmv;
	int flag = agbpoke_init(NULL);

	wk->agbpokemon = FALSE;

	// AGBポケモンが刺さっていなければ何もしない
	if(flag != AGBPOKE_ERROR_OK){
		return;
	}

	// システムへカセットタイプを通知する
	pmv = 0;	// unknown
	switch(agbpoke_getPokemonType()){
	case CASTYPE_RUBY:
		pmv = VERSION_RUBY;
		break;
	case CASTYPE_SAPPHIRE:
		pmv = VERSION_SAPPHIRE;
		break;
	case CASTYPE_GREEN:
		pmv = VERSION_GREEN;
		break;
	case CASTYPE_RED:
		pmv = VERSION_RED;
		break;
	case CASTYPE_EMERALD:
		pmv = VERSION_EMERALD;
		break;
	}
	sys_InitAgbCasetteVer(pmv);
#ifdef DEBUG_ONLY_FOR_mituhara
	OS_TPrintf("AGBカセットバージョン: %d\n", pmv);
#endif

#ifndef DEBUG_ONLY_FOR_mituhara
	// DP側の全国ずかんモードがONになっていなければポケモンカセットのメニューは表示されない
	if(ZukanWork_GetZenkokuZukanFlag(wk->zw) == FALSE){
		return;
	}
#endif

	// DPと同じ言語でなければメニューは表示しない
	if(agbpoke_getPokemonLanguage() != CasetteLanguage)
		return;

	// ポケモンのタイプを設定する
	wk->agbpokemon = agbpoke_getPokemonType() + 1;

	/* スリープ時のカートリッジ抜けを有効にするための関数呼び出し */
	MysteryLib_SetAgbCartridgeIntr2();
}


//------------------------------------------------------------------
/**
 * @brief	ビーコン取得プロセス
 * 		※threadになってるわけではありません
 */
//------------------------------------------------------------------
static void StartMenuBeacon_Proc(STARTMENU_WORK *wk)
{
	int flag;

	switch(wk->beacon_seq){
	case STARTMENU_BEACON_SEQ_WAIT:
		// 外部からシーケンスを変更されない限り動かない
		break;

	case STARTMENU_BEACON_SEQ_INIT:
		wk->beacon_seq = STARTMENU_BEACON_SEQ_INIT2;
		break;
	case STARTMENU_BEACON_SEQ_INIT2:
		// * パーティーゲーム検索の通信処理開始（子機状態のみ）
		CommStateEnterPartyGameScanChild(wk->sv);
		wk->beacon_wait = BEACON_GATHER_TIME;
		wk->beacon_seq = STARTMENU_BEACON_SEQ_TIMER;
		wk->beacon_status = 0;
		// すでに「ふしぎな　おくりもの」メニューが表示されていたらポップアップはしない
		if(FUSHIGIDATA_IsFushigiMenu(wk->fdata) == TRUE){
			wk->beacon_status |= PARTYGAME_MYSTERY_BCON;
			wk->beacon_disp_status |= PARTYGAME_MYSTERY_BCON;
		}

		break;

	case STARTMENU_BEACON_SEQ_TIMER:
		// すでにポップアップ予約中
		if(wk->beacon_msg_wait){
			break;
		}
		// ビーコン収集中
		flag = CommStateGetPartyGameBit();

#ifdef DEBUG_ONLY_FOR_iwasawa
		// デバッグ中
#if 1
		if(sys.trg & PAD_BUTTON_L){
			flag |= PARTYGAME_RANGER_BCON;
		}
		if(sys.trg & PAD_BUTTON_R){
			flag |= PARTYGAME_WII_BCON;
		}
		if(sys.trg & PAD_BUTTON_Y){
			flag |= PARTYGAME_MYSTERY_BCON;
		}
#else
		flag |= PARTYGAME_RANGER_BCON;
		flag |= PARTYGAME_WII_BCON;
		flag |= PARTYGAME_MYSTERY_BCON;
#endif
#endif

		// 前回まで表示していないビットのみ立てる
		flag = ~wk->beacon_status & flag;
		// 何かのビーコンを拾っていて、割り込みメッセージ表示中でなくて、すでに予約済みでなくて、まだ表示してない場合
		if(	flag &&
			wk->beacon_msg_seq == BEACON_MSGSEQ_NOP &&
			wk->beacon_msg_wait == 0 &&
			wk->beacon_status != flag){

			wk->redrawflag = TRUE;
			if(flag & PARTYGAME_MYSTERY_BCON){
				wk->mystery = TRUE,		flag = PARTYGAME_MYSTERY_BCON;
			}
			if(flag & PARTYGAME_RANGER_BCON){
				wk->pokemonranger = TRUE,	flag = PARTYGAME_RANGER_BCON;
			}
			if(flag & PARTYGAME_WII_BCON){
				wk->wii = TRUE,			flag = PARTYGAME_WII_BCON;
			}
			// ふしぎビーコンとレンジャービーコンの場合は割り込みメッセージ表示
			if(flag & (PARTYGAME_MYSTERY_BCON|PARTYGAME_RANGER_BCON)){
				wk->req_popup = TRUE;
			}
			// ここでようやく表示済みフラグの更新
			wk->beacon_status |= flag;
		}
		if(--wk->beacon_wait == 0){
			// パーティーゲームサーチの終了処理
			CommStateExitPartyGameScan();
			wk->beacon_seq = STARTMENU_BEACON_SEQ_WAIT;
		}
		break;

	case STARTMENU_BEACON_SEQ_CANCEL:
		// 強制終了処理(ゲームが開始されたとか)
		CommStateExitPartyGameScan();
		wk->beacon_seq = STARTMENU_BEACON_SEQ_WAIT;
		break;
	}
}


//------------------------------------------------------------------
/**
 * @brief	ビーコンを取得した際に表示する画面
 * @param	NONE
 * @return	NONE
 */
//------------------------------------------------------------------
static BOOL BeaconMessage_Proc(STARTMENU_WORK *wk)
{
	MYSTERY_WIN mw;
	BEACON_MSG_TABLE *tbl;
	int msg, status;

	switch(wk->beacon_msg_seq){
	case BEACON_MSGSEQ_NOP:
		if(wk->beacon_msg_wait == 0)	return FALSE;
		// ビーコンを拾ってから数フレーム後に発動
		if(--wk->beacon_msg_wait == 0)
			wk->beacon_msg_seq = BEACON_MSGSEQ_INIT;
		return TRUE;
		break;

	case BEACON_MSGSEQ_INIT:
		// 初期化
		MenuWinGraphicSet(wk->bgl, GF_BGL_FRAME1_M, STARTMENU_FCHR1, STARTMENU_FCOL1, 0, HEAPID_STARTMENU);
		MenuWinGraphicSet(wk->bgl, GF_BGL_FRAME1_M, STARTMENU_FCHR2, STARTMENU_FCOL2, 1, HEAPID_STARTMENU);
		GF_BGL_ScrClear(wk->bgl, GF_BGL_FRAME1_M);
		*((u16 *)HW_BG_PLTT + 33) = RGB(26, 26, 26);
		wk->beacon_msg_seq = BEACON_MSGSEQ_INIT_DISP;
		break;

	case BEACON_MSGSEQ_INIT_DISP:
		// スクリーン初期化
		MysteryLib_WinInit1(&mw, &wk->beacon_win,
				STARTMENU_WCOL_SELECT, NARC_msg_bconfind_dat, STARTMENU_FCHR1, STARTMENU_FCOL1);

		// １度表示したメニューは表示しないために表示したフラグを覚えておく
		status = wk->beacon_status & ~wk->beacon_disp_status;

#ifdef DEBUG_ONLY_FOR_iwasawa
//		status |= (PARTYGAME_MYSTERY_BCON);
#endif
		if(status & PARTYGAME_MYSTERY_BCON){
			if(wk->menu_flag & PARTYGAME_MYSTERY_BCON){
				tbl = &BeaconMsgTable[0];	// ふしぎ追加
			}else{
				tbl = &BeaconMsgTable[1];	// 追加できなかった
			}
		} else if(status & PARTYGAME_RANGER_BCON){
			if(wk->menu_flag & PARTYGAME_RANGER_BCON){
				tbl = &BeaconMsgTable[2];	// レンジャー追加
			}else{
				tbl = &BeaconMsgTable[3];	// 追加できなかった
			}
		} else if(status & STARTMENU_FIRSTGAME_SELECT){
			tbl = &BeaconMsgTable[4];	// さいしょからはじめるをえらんだ時のメッセージ
			mw.winmode = MYSTERYLIB_WINTYPE_NONE;
			mw.dx = 8;
			mw.dy = 4;
//			status = 0;	// 何度でも表示させたいので覚えさせない
		}

		MysteryLib_WinInit2(&mw, tbl->width, tbl->height, BEACON_MSG_WCHR);
		mw.screen = GF_BGL_FRAME1_M;
		MysteryLib_CreateWin(wk->bgl, &mw, tbl->sx, tbl->sy, tbl->msg);
		GF_BGL_ScrPalChange(wk->bgl, GF_BGL_FRAME1_M,
			GF_BGL_BmpWinGet_PosX(mw.win),	GF_BGL_BmpWinGet_PosY(mw.win),
			GF_BGL_BmpWinGet_SizeX(mw.win), GF_BGL_BmpWinGet_SizeY(mw.win),
			STARTMENU_WCOL_SELECT);

		if(	(status & STARTMENU_FIRSTGAME_SELECT) &&
			(!(status & (PARTYGAME_MYSTERY_BCON|PARTYGAME_RANGER_BCON)))){
			int i;
			//ぼうけんにでる、メニューにもどるのメニューウィンドウを作成
			for(i = 0;i < 2;i++){
				MysteryLib_WinInit1(&mw, &wk->beacon_win_sub[i],
					STARTMENU_WCOL_SELECT, NARC_msg_bconfind_dat, STARTMENU_FCHR1, STARTMENU_FCOL1);
				tbl = &BeaconMsgTable[5+i];
				mw.dy = 4;
				MysteryLib_WinInit2(&mw, tbl->width, tbl->height, STARTMENU_NGAME_WCHR+(STARTMENU_NGAME_WCHR_ONE_SIZ*i));
				mw.screen = GF_BGL_FRAME1_M;
				MysteryLib_CreateWin(wk->bgl, &mw, tbl->sx, tbl->sy, tbl->msg);
			}
			wk->cursor_ng = 0;
			RedrawWindowFrameNewGame(wk,-1);
			wk->beacon_msg_seq = BEACON_MSGSEQ_INIT_MAIN_FMSG;
			wk->beacon_key_wait = BEACON_KEY_WAIT_FMSG;
		}else{
			wk->beacon_disp_status |= status;
			wk->beacon_msg_seq = BEACON_MSGSEQ_INIT_MAIN;
			wk->beacon_key_wait = BEACON_KEY_WAIT;
		}

		GF_Disp_GX_VisibleControl(GX_PLANEMASK_BG0, VISIBLE_OFF);
		GF_Disp_GX_VisibleControl(GX_PLANEMASK_BG2, VISIBLE_OFF);
		GF_Disp_GX_VisibleControl(GX_PLANEMASK_BG1, VISIBLE_ON);
		break;

	case BEACON_MSGSEQ_INIT_MAIN:
		// キー入力待ち
		if(wk->beacon_key_wait){
			wk->beacon_key_wait--;
		} else {
			int old_key = wk->key_mode;
			int ret = InputCheck(wk);
			if(ret & (PAD_BUTTON_DECIDE|PAD_BUTTON_CANCEL)){
				if(old_key != wk->key_mode){
					RedrawWindowFrame(wk, wk->cursor);
				}
				GF_BGL_BmpWinDel(&wk->beacon_win);
				wk->beacon_msg_seq = BEACON_MSGSEQ_INIT_FINISH;
				wk->beacon_result = ret;
				Snd_SePlay(SEQ_SE_DP_SELECT);
			}
		}
		break;
	case BEACON_MSGSEQ_INIT_MAIN_FMSG:

		// キー入力待ち
		if(wk->beacon_key_wait){
			if(--wk->beacon_key_wait == 0){	//表示を変える
				RedrawWindowFrameNewGame(wk, 0);
			}
		} else {
			int ret = InputCheckNewGame(wk);

			// 選択されているウィンドウをパレットアニメーション
			SelectPalAnim(wk);

			if(ret & (PAD_BUTTON_DECIDE|PAD_BUTTON_CANCEL)){
				GF_BGL_BmpWinDel(&wk->beacon_win);
				GF_BGL_BmpWinDel(&wk->beacon_win_sub[0]);
				GF_BGL_BmpWinDel(&wk->beacon_win_sub[1]);
				RedrawWindowFrame(wk, wk->cursor);
				wk->beacon_msg_seq = BEACON_MSGSEQ_INIT_FINISH;
				wk->beacon_result = ret;
				Snd_SePlay(SEQ_SE_DP_SELECT);
			}
		}
		break;

	case BEACON_MSGSEQ_INIT_FINISH:
		// 終了
		GF_Disp_GX_VisibleControl(GX_PLANEMASK_BG0, VISIBLE_ON);
		GF_Disp_GX_VisibleControl(GX_PLANEMASK_BG2, VISIBLE_ON);
		GF_Disp_GX_VisibleControl(GX_PLANEMASK_BG1, VISIBLE_OFF);
		wk->beacon_msg_seq = BEACON_MSGSEQ_NOP;
		break;
	}
	return TRUE;
}


//------------------------------------------------------------------
/**
 * @brief	毎フレーム行う処理
 * @param	NONE
 * @return	NONE
 */
//------------------------------------------------------------------
// 条件分岐しないABS
#define ABS(x)		(((x) ^ ((x)>>31)) - ((x)>>31))
#define SCROLL_MAX_SPEED	(12 * FX32_ONE)
static void StartMenuProc(STARTMENU_WORK *wk)
{
	fx32 speed;

	// スクロール処理
	if(wk->scrolly != wk->target){
		speed = (wk->target - wk->scrolly) / 4;
		if(ABS(speed) > SCROLL_MAX_SPEED){
			if(speed > 0){
				speed =	SCROLL_MAX_SPEED;
			}else{
				speed = -SCROLL_MAX_SPEED;
			}
		}
		wk->scrolly += speed;

		if(ABS(wk->target - wk->scrolly) < FX32_ONE/8)
			wk->scrolly = wk->target;

		GF_BGL_ScrollReq(wk->bgl, GF_BGL_FRAME0_M, GF_BGL_SCROLL_Y_SET, wk->scrolly / FX32_ONE);
		GF_BGL_ScrollReq(wk->bgl, GF_BGL_FRAME2_M, GF_BGL_SCROLL_Y_SET, wk->scrolly / FX32_ONE);
	}
}

//------------------------------------------------------------------
/**
 * @brief	スクリーン初期化
 * @param	NONE
 * @return	NONE
 */
//------------------------------------------------------------------
static void InitStartMenuScreen(STARTMENU_WORK *wk)
{
	GF_BGL_DISPVRAM tbl = {
		GX_VRAM_BG_128_A,				// メイン2DエンジンのBG
		GX_VRAM_BGEXTPLTT_NONE,			// メイン2DエンジンのBG拡張パレット
		GX_VRAM_SUB_BG_128_C,			// サブ2DエンジンのBG
		GX_VRAM_SUB_BGEXTPLTT_NONE,			// サブ2DエンジンのBG拡張パレット
		GX_VRAM_OBJ_64_E,				// メイン2DエンジンのOBJ
		GX_VRAM_OBJEXTPLTT_NONE,			// メイン2DエンジンのOBJ拡張パレット
		GX_VRAM_SUB_OBJ_16_I,			// サブ2DエンジンのOBJ
		GX_VRAM_SUB_OBJEXTPLTT_NONE,		// サブ2DエンジンのOBJ拡張パレット
		GX_VRAM_TEX_0_B,				// テクスチャイメージスロット
		GX_VRAM_TEXPLTT_01_FG			// テクスチャパレットスロット
	};
	GF_BGL_SYS_HEADER BGsys_data = { GX_DISPMODE_GRAPHICS, GX_BGMODE_0, GX_BGMODE_0, GX_BG0_AS_2D };

	GF_Disp_SetBank( &tbl );

	/* BG SYSTEM */
	GF_BGL_InitBG( &BGsys_data );

	//上画面をサブ,下画面をメインに切り替え
	GX_SetDispSelect(GX_DISP_SELECT_SUB_MAIN);

	/* メニューを表示するBG */
	MysteryLib_BgInitFrame(wk->bgl, GF_BGL_FRAME0_M, GF_BGL_SCRSIZ_256x512, 0xF000, 0x0000); /* MAIN DISP BG0 */
	G2_SetBG0Priority(2);
	GF_BGL_ClearCharSet(GF_BGL_FRAME0_M, 32, 0, HEAPID_STARTMENU);
	GF_BGL_ScrClear(wk->bgl,GF_BGL_FRAME0_M);
	/* ビーコン取得時に表示するメッセージBG */
	MysteryLib_BgInitFrame(wk->bgl, GF_BGL_FRAME1_M, GF_BGL_SCRSIZ_256x256, 0xD800, 0x8000); /* MAIN DISP BG1 */
	G2_SetBG1Priority(1);
	GF_BGL_ClearCharSet(GF_BGL_FRAME1_M, 32, 0, HEAPID_STARTMENU);
	GF_BGL_ScrClear(wk->bgl,GF_BGL_FRAME1_M);
	/* 通信アイコンを表示するBG画面 */
	MysteryLib_BgInitFrame(wk->bgl, GF_BGL_FRAME2_M, GF_BGL_SCRSIZ_256x512, 0xE000, 0x0000); /* MAIN DISP BG2 */
	G2_SetBG2Priority(0);
	GF_BGL_ClearCharSet(GF_BGL_FRAME2_M, 32, 0, HEAPID_STARTMENU);
	GF_BGL_ScrClear(wk->bgl,GF_BGL_FRAME2_M);

	MSG_PrintInit();

	/* メッセージのフォントカラーを設定 */
	SystemFontPaletteLoad(PALTYPE_MAIN_BG, STARTMENU_WCOL_NORMAL * 32, HEAPID_STARTMENU);
	SystemFontPaletteLoad(PALTYPE_MAIN_BG, STARTMENU_WCOL_SELECT * 32, HEAPID_STARTMENU);
	*((u16 *)HW_BG_PLTT +	0) = RGB( 0,	0,	0);

	*((u16 *)HW_BG_PLTT + 31) = RGB(26, 26, 26);	// ウィンドウの背景
	//ウィンドウ枠キャラ、パレットをセット
	MenuWinGraphicSet(wk->bgl, GF_BGL_FRAME0_M, STARTMENU_FCHR1, STARTMENU_FCOL1, 0, HEAPID_STARTMENU);
	MenuWinGraphicSet(wk->bgl, GF_BGL_FRAME0_M, STARTMENU_FCHR2, STARTMENU_FCOL2, 1, HEAPID_STARTMENU);
	// 選択してないウィンドウの白ライン
	*((u16 *)HW_BG_PLTT + 33) = RGB(26, 26, 26);

}


//------------------------------------------------------------------
/**
 * @brief	スクロールカーソルの表示準備
 * @param	NONE
 * @return	NONE
 */
//------------------------------------------------------------------
static void StartMenuInitClact(STARTMENU_WORK *wk)
{
	MysteryLib_InitCPManager();
	MysteryLib_InitClactSystem();
	MysteryLib_InitClact(ARC_MYSTERY_GRA,
					 NARC_mystery_title_cursor_lz_cngr,
					 NARC_mystery_title_cursol_nclr,
					 NARC_mystery_title_cursor_lz_ccer,
					 NARC_mystery_title_cursor_lz_canr,
					 GF_BGL_MAIN_DISP);
	wk->clcursor[0] =
		MysteryLib_MakeCLACT(GF_BGL_MAIN_DISP,wk->clcursor[0],ACT_AL_OX,ACT_AL_OY0,0);
	CLACT_SetDrawFlag(wk->clcursor[0], TRUE	);
	CLACT_SetAnmFlag(wk->clcursor[0], FALSE);
	wk->clcursor[1] =
		MysteryLib_MakeCLACT(GF_BGL_MAIN_DISP,wk->clcursor[1],ACT_AL_OX,ACT_AL_OY1, 1);
	CLACT_SetDrawFlag(wk->clcursor[1], TRUE);
	CLACT_SetAnmFlag(wk->clcursor[1], FALSE);
}


//------------------------------------------------------------------
/**
 * @brief	通信アイコンのグラフィックス準備
 * @param	NONE
 * @return	NONE
 */
//------------------------------------------------------------------
static void WirelessIconInit(STARTMENU_WORK *wk)
{
	// メイン画面ＢＧパレット転送
	ArcUtil_PalSet(ARC_MYSTERY_GRA, NARC_mystery_wicon_nclr, PALTYPE_MAIN_BG, STARTMENU_WICON_PAL*32, 32*1, HEAPID_STARTMENU);
	// メイン画面BG1キャラ転送
	ArcUtil_BgCharSet(ARC_MYSTERY_GRA, NARC_mystery_wicon_ncgr, wk->bgl,
				GF_BGL_FRAME2_M, WIRELESS_CHR_BASE, WIRELESS_CHR_SIZ*0x20, 0, HEAPID_STARTMENU);
}


//------------------------------------------------------------------
/**
 * @brief	指定座標に通信アイコンを表示
 * @param	NONE
 * @return	NONE
 */
//------------------------------------------------------------------
static void SetWirelessIcon(STARTMENU_WORK *wk, int sx, int sy, int flag)
{
	u16 *scrn = (u16 *)GF_BGL_ScreenAdrsGet(wk->bgl, GF_BGL_FRAME2_M);
	int base = WIRELESS_ICON_BASE;

	if(flag == 2)	base = WIRELESS_ICON_BASE + 4;

	scrn[sy * 32 + sx + 0] = base + 0;
	scrn[sy * 32 + sx + 1] = base + 1;
	sy++;
	scrn[sy * 32 + sx + 0] = base + 2;
	scrn[sy * 32 + sx + 1] = base + 3;
	GF_BGL_LoadScreenReq(wk->bgl, GF_BGL_FRAME2_M);
}
static void ClrWirelessIcon(STARTMENU_WORK *wk, int sx, int sy)
{
	u16 *scrn = (u16 *)GF_BGL_ScreenAdrsGet(wk->bgl, GF_BGL_FRAME2_M);
	scrn[sy * 32 + sx + 0] = 0;//WIRELESS_ICON_BASE + 4;
	scrn[sy * 32 + sx + 1] = 0;//WIRELESS_ICON_BASE + 4;
	sy++;
	scrn[sy * 32 + sx + 0] = 0;//WIRELESS_ICON_BASE + 4;
	scrn[sy * 32 + sx + 1] = 0;//WIRELESS_ICON_BASE + 4;
	GF_BGL_LoadScreenReq(wk->bgl, GF_BGL_FRAME2_M);
}


//------------------------------------------------------------------
/**
 * @brief	つづきからはじめるの内容表示
 * @param	NONE
 * @return	NONE
 */
//------------------------------------------------------------------
#define STARTMENU_MARGIN_L	32
#define	STARTMENU_BLUE		(GF_PRINTCOLOR_MAKE(7, 8, 15))
#define	STARTMENU_RED		(GF_PRINTCOLOR_MAKE(3, 4, 15))

static void StartMenuContinueSub1(GF_BGL_BMPWIN *win, MSGDATA_MANAGER *msgman, WORDSET *word, GF_PRINTCOLOR color, u32 msgid, int y)
{
	int width, wsize;
	STRBUF * msg;

	msg = MSGDAT_UTIL_AllocExpandString(word, msgman, msgid, HEAPID_STARTMENU);
	width = FontProc_GetPrintStrWidth(FONT_SYSTEM, msg,	FontHeaderGet(FONT_SYSTEM, FONT_HEADER_SPACE_X));
	wsize = GF_BGL_BmpWinGet_SizeX(win) * 8 - (width + STARTMENU_MARGIN_L);
	GF_STR_PrintColor(win, FONT_SYSTEM, msg, wsize, y, MSG_NO_PUT, color, NULL);
	STRBUF_Delete(msg);
}
static void StartMenuContinueSub2(WORDSET *word, int value)
{
	int keta, type;
	if (value >= 100) {
		keta = 3;
		type = NUMBER_DISPTYPE_LEFT;
	}else if(value >= 10){
		keta = 3;
		type = NUMBER_DISPTYPE_SPACE;
	}else{
		keta = 3 - 1;
		type = NUMBER_DISPTYPE_SPACE;
	}
	WORDSET_RegisterNumber(word, 0, value, keta, type, NUMBER_CODETYPE_DEFAULT);
}

static BOOL StartMenuContinue(void *p, int index, MYSTERY_WIN *mw, int y)
{
	int i, width, wsize;
	STRBUF * msg;
	WORDSET *word;
	MSGDATA_MANAGER *msgman;
	STARTMENU_WORK *wk = (STARTMENU_WORK *)p;
	GF_PRINTCOLOR color;

	msgman = MSGMAN_Create(MSGMAN_TYPE_DIRECT, ARC_MSG, NARC_msg_startmenu_dat, HEAPID_STARTMENU);
	word = WORDSET_Create(HEAPID_STARTMENU);

	// 女性(FEMALE)なら赤、それ以外(MALE, NEUTRAL)ならば青
	if(MyStatus_GetMySex(wk->mst) == PM_FEMALE){
		color = STARTMENU_RED;
	}else{
		color = STARTMENU_BLUE;
	}

	// さいしょの１行を表示
	MysteryLib_CreateWin(wk->bgl, mw, MENU_XOFS, y, StartMenuWinTable[index].msgid);
	// ２行目以降を表示
	for(i = 1; i < sizeof(StartMenuContinueTable) / sizeof(u32); i++){
		// ずかんを持っていなかったら、そもそも項目を表示しない
		if(i == 4 && wk->zukangetflag == FALSE){
			continue;
		}
		// それ以外は普通に表示して良い
		msg = MSGDAT_UTIL_AllocExpandString(word, msgman, StartMenuContinueTable[i], HEAPID_STARTMENU);
		GF_STR_PrintColor(mw->win, FONT_SYSTEM, msg, STARTMENU_MARGIN_L, i*16, MSG_NO_PUT, color, NULL);
		STRBUF_Delete(msg);
	}

	// 主人公の情報表示
	WORDSET_RegisterPlayerName(word, 0, wk->mst);
	StartMenuContinueSub1(mw->win, msgman, word, color, mes_startmenu_17, 16*1);
	// プレイ時間を表示
	StartMenuContinueSub2(word, PLAYTIME_GetHour(wk->ptime));
	WORDSET_RegisterNumber(word, 1, PLAYTIME_GetMinute(wk->ptime), 2, NUMBER_DISPTYPE_ZERO, NUMBER_CODETYPE_DEFAULT);
	StartMenuContinueSub1(mw->win, msgman, word, color, mes_startmenu_18, 16*2);
	// もっているバッチ
	WORDSET_RegisterNumber(word, 0, wk->badgecount, 2, NUMBER_DISPTYPE_LEFT, NUMBER_CODETYPE_DEFAULT);
	StartMenuContinueSub1(mw->win, msgman, word, color, mes_startmenu_20, 16*3);
	// ポケモンずかん表示
	if(wk->zukangetflag){
		StartMenuContinueSub2(word, ZukanWork_GetZukanPokeGetCount(wk->zw));
		StartMenuContinueSub1(mw->win, msgman, word, color, mes_startmenu_19, 16*4);
	}
	// まとめて表示
	BmpMenuWinWrite(mw->win, WINDOW_TRANS_ON, mw->fchr, mw->fcol);
	// 描いたよフラグをON
	wk->menuflag[index] = StartMenuWinTable[index].mark;

	WORDSET_Delete(word);
	MSGMAN_Delete(msgman);

	return TRUE;
}


//------------------------------------------------------------------
/**
 * @brief	ＡＧＢポケモンの有無を調べてメニュー表示
 * @param	NONE
 * @return	NONE
 */
//------------------------------------------------------------------
static BOOL StartMenuAgbPokemon(void *p, int index, MYSTERY_WIN *mw, int y)
{
	int msg;
	STARTMENU_WORK *wk = (STARTMENU_WORK *)p;

	// AGBカートリッジの存在は別のタイミングで行っています
	if(wk->agbpokemon == FALSE)	return FALSE;

	// 文字列を選択
	switch(wk->agbpokemon - 1){
	case CASTYPE_RUBY:
		msg = mes_startmenu_ruby;
		break;
	case CASTYPE_SAPPHIRE:
		msg = mes_startmenu_sapphire;
		break;
	case CASTYPE_GREEN:
		msg = mes_startmenu_green;
		break;
	case CASTYPE_RED:
		msg = mes_startmenu_red;
		break;
	case CASTYPE_EMERALD:
		msg = mes_startmenu_emerald;
		break;
	}
	// メニュー表示
	MysteryLib_CreateWin(wk->bgl, mw, MENU_XOFS, y, msg);
	ClrWirelessIcon(wk, MENU_WIDTH, y);
	wk->menuflag[index] = StartMenuWinTable[index].mark;

	return TRUE;
}


//------------------------------------------------------------------
/**
 * @brief	ふしぎな　おくりものを表示
 * @param	NONE
 * @return	NONE
 */
//------------------------------------------------------------------
static BOOL StartMenuCheckMystery(void *p, int index, MYSTERY_WIN *mw, int y)
{
	STARTMENU_WORK *wk = (STARTMENU_WORK *)p;

	// ふしぎな　おくりものを強制的にONにする場合の処理
	if(wk->mystery == FALSE){
		// すでにふしぎな　おくりものは表示可能？
		if(FUSHIGIDATA_IsFushigiMenu(wk->fdata) == TRUE){
			wk->mystery = TRUE;
			IWASAWA_PRINT("不思議な贈り物On <- 贈り物セーブデータ成立\n");
		}
		// ゲーム中のあいことばが成立している？
		if(SYSTEMDATA_GetWifiMPOpenFlag(SaveData_GetSystemData(wk->sv)) == TRUE){
			wk->mystery = TRUE;
			IWASAWA_PRINT("不思議な贈り物On <- 合言葉成立\n");
		}
		// AGBでの配布用カセットが刺さってる？
		if(GetAgbCartridgeDataSize()){
			wk->mystery = TRUE;
			MysteryLib_SetAgbCartridgeIntr(TRUE);	/* AGBカートリッジの抜け検出ON */
			IWASAWA_PRINT("不思議な贈り物On <- AGB配布\n");
		}
	}

	// ふしぎな　おくりものを強制的にOFFにする場合の処理
	if(wk->mystery == TRUE){
		// ずかんを持っていなければ強制的にOFFする
		if(wk->zukangetflag == FALSE){
			wk->mystery = FALSE;
			IWASAWA_PRINT("不思議な贈り物強制Off <- 図鑑がまだない\n");
		}
	}

	// 実際のチェックはStartMenuBeacon_Procで行っています
	if(wk->mystery == TRUE){
		// メニュー表示
		MysteryLib_CreateWin(wk->bgl, mw, MENU_XOFS, y, StartMenuWinTable[index].msgid);
		ClrWirelessIcon(wk, MENU_WIDTH, y);
		wk->menuflag[index] = StartMenuWinTable[index].mark;
		wk->menu_flag |= PARTYGAME_MYSTERY_BCON;
		FUSHIGIDATA_SetFushigiMenu(wk->fdata);
		return TRUE;
	}

	return FALSE;
}

//------------------------------------------------------------------
/**
 * @brief	ポケモンレンジャーとの接続を表示
 * @param	NONE
 * @return	NONE
*/
//------------------------------------------------------------------
static BOOL StartMenuCheckRanger(void *p, int index, MYSTERY_WIN *mw, int y)
{
	STARTMENU_WORK *wk = (STARTMENU_WORK *)p;
	// 実際のチェックはStartMenuBeacon_Procで行っています

	if(wk->pokemonranger == TRUE && wk->zukangetflag == TRUE){
		// メニュー表示
		MysteryLib_CreateWin(wk->bgl, mw, MENU_XOFS, y, StartMenuWinTable[index].msgid);
		SetWirelessIcon(wk, MENU_WIDTH, y, 1);
		wk->iconflag[index] = 1;
		wk->menuflag[index] = StartMenuWinTable[index].mark;
		wk->menu_flag |= PARTYGAME_RANGER_BCON;
		return TRUE;
	}
	return FALSE;
}


//------------------------------------------------------------------
/**
 * @brief	Wiiのメニューを表示
 * @param	NONE
 * @return	NONE
 */
//------------------------------------------------------------------
static BOOL StartMenuCheckWii(void *p, int index, MYSTERY_WIN *mw, int y)
{
	STARTMENU_WORK *wk = (STARTMENU_WORK *)p;
	// 実際のチェックはStartMenuBeacon_Procで行っています

	if(wk->wii == TRUE){
		// メニュー表示
		MysteryLib_CreateWin(wk->bgl, mw, MENU_XOFS, y, StartMenuWinTable[index].msgid);
		wk->iconflag[index] = 1;
		SetWirelessIcon(wk, MENU_WIDTH, y, 1);
		wk->menuflag[index] = StartMenuWinTable[index].mark;
		return TRUE;
	}
	return FALSE;
}


//------------------------------------------------------------------
/**
 * @brief	Wi-Fi設定
 * @param	NONE
 * @return	NONE
 */
//------------------------------------------------------------------
static BOOL StartMenuSetWifi(void *p, int index, MYSTERY_WIN *mw, int y)
{
	STARTMENU_WORK *wk = (STARTMENU_WORK *)p;
	// メニュー表示
	MysteryLib_CreateWin(wk->bgl, mw, MENU_XOFS, y, StartMenuWinTable[index].msgid);
	wk->iconflag[index] = 2;
	SetWirelessIcon(wk, MENU_WIDTH, y, 2);
	wk->menuflag[index] = StartMenuWinTable[index].mark;
	return TRUE;
}

//------------------------------------------------------------------
/*
 * @brief	PHC
 * @param	NONE
 * @return	NONE
 */
//------------------------------------------------------------------
static BOOL StartMenuSetPHC(void *p, int index, MYSTERY_WIN *mw, int y)
{
	STARTMENU_WORK *wk = (STARTMENU_WORK *)p;
	// メニュー表示
	MysteryLib_CreateWin(wk->bgl, mw, MENU_XOFS, y, StartMenuWinTable[index].msgid);
	ClrWirelessIcon(wk, MENU_WIDTH, y);
	wk->menuflag[index] = StartMenuWinTable[index].mark;
	return TRUE;
}

//------------------------------------------------------------------
/*
 * @brief	E-MAIL
 * @param	NONE
 * @return	NONE
 */
//------------------------------------------------------------------
static BOOL StartMenuSetEmail(void *p, int index, MYSTERY_WIN *mw, int y)
{
	STARTMENU_WORK *wk = (STARTMENU_WORK *)p;
	// メニュー表示
	MysteryLib_CreateWin(wk->bgl, mw, MENU_XOFS, y, StartMenuWinTable[index].msgid);
	ClrWirelessIcon(wk, MENU_WIDTH, y);
	wk->menuflag[index] = StartMenuWinTable[index].mark;
	return TRUE;
}


//------------------------------------------------------------------
/**
 * @brief	メニュー作成
 * @param	NONE
 * @return	NONE
 */
//------------------------------------------------------------------
static BOOL CreateStartMenu(STARTMENU_WORK *wk)
{
	STARTMENU_DATA *smd;
	MYSTERY_WIN mw;
	int i, y, ret;

	ret = FALSE;
	y = 1;
	wk->list_max = 0;

	wk->chrbase = STARTMENU_WCHR;
	for(i = 0; i < MENU_WIN_MAX; i++){
		smd = &StartMenuWinTable[i];

		MysteryLib_WinInit1(&mw, &wk->mwin[i], STARTMENU_WCOL_NORMAL, NARC_msg_startmenu_dat, STARTMENU_FCHR1, STARTMENU_FCOL1);
		MysteryLib_WinInit2(&mw, MENU_WIDTH, smd->height,/* NULL,*/ wk->chrbase);
		if(smd->func){
			// func内部で表示
			if(wk->menuflag[i]){
				GF_BGL_BmpWinSet_PosX(mw.win, MENU_XOFS);
				GF_BGL_BmpWinSet_PosY(mw.win, y);

				BmpMenuWinWrite(mw.win, WINDOW_TRANS_ON, mw.fchr, mw.fcol);

				if(wk->iconflag[i]){
					SetWirelessIcon(wk, MENU_WIDTH, y, wk->iconflag[i]);
				}else{
					ClrWirelessIcon(wk, MENU_WIDTH, y);
				}
				y += smd->height + 2;
				ret = TRUE;
			}else if(smd->func(wk, i, &mw, y) == TRUE){
				y += smd->height + 2;
				ret = TRUE;
			}
		}else{
			// 通常表示
			MysteryLib_CreateWin(wk->bgl, &mw, MENU_XOFS, y, smd->msgid);
			wk->menuflag[i] = smd->mark;
			y += smd->height + 2;
		}
		wk->chrbase += MENU_WIDTH * smd->height;

		//有効な項目数を数える
		if(wk->menuflag[i]){
			wk->list_max++;
		}
	}
	SetCursorVisible(wk);
	RedrawWindowFrame(wk, wk->cursor);
	return ret;
}


//------------------------------------------------------------------
/**
 * @brief	ウィンドウの枠(フレーム)を再表示
 * @param	NONE
 * @return	NONE
 */
//------------------------------------------------------------------
static void RedrawWindowFrame(STARTMENU_WORK *wk, int select)
{
	int i;
	for(i = 0; i < sizeof(StartMenuWinTable) / sizeof(STARTMENU_DATA); i++){

		if(GF_BGL_BmpWinAddCheck(&wk->mwin[i]) == FALSE){
			continue;
		}
		if(i == 0 && wk->target == SCR_TARGET_PAGE2){
			continue;
		}

		if( !( i >= (select-5) && i <= (select+5) ) ){
			continue;
		}

		if(wk->key_mode == APP_KTST_TOUCH){
			BmpMenuWinWrite(&wk->mwin[i], WINDOW_TRANS_OFF, STARTMENU_FCHR2, STARTMENU_FCOL1);
			GF_BGL_ScrPalChange(wk->bgl, GF_BGL_FRAME0_M,
				GF_BGL_BmpWinGet_PosX(&wk->mwin[i]),	GF_BGL_BmpWinGet_PosY(&wk->mwin[i]),
				GF_BGL_BmpWinGet_SizeX(&wk->mwin[i]), GF_BGL_BmpWinGet_SizeY(&wk->mwin[i]),
				STARTMENU_WCOL_SELECT);
		}else if(i == select){
			BmpMenuWinWrite(&wk->mwin[i], WINDOW_TRANS_OFF, STARTMENU_FCHR2, STARTMENU_FCOL2);
			GF_BGL_ScrPalChange(wk->bgl, GF_BGL_FRAME0_M,
				GF_BGL_BmpWinGet_PosX(&wk->mwin[i]),	GF_BGL_BmpWinGet_PosY(&wk->mwin[i]),
				GF_BGL_BmpWinGet_SizeX(&wk->mwin[i]), GF_BGL_BmpWinGet_SizeY(&wk->mwin[i]),
				STARTMENU_WCOL_SELECT);
		} else {
			BmpMenuWinWrite(&wk->mwin[i], WINDOW_TRANS_OFF, STARTMENU_FCHR1, STARTMENU_FCOL1);
			GF_BGL_ScrPalChange(wk->bgl, GF_BGL_FRAME0_M,
				GF_BGL_BmpWinGet_PosX(&wk->mwin[i]),	GF_BGL_BmpWinGet_PosY(&wk->mwin[i]),
				GF_BGL_BmpWinGet_SizeX(&wk->mwin[i]), GF_BGL_BmpWinGet_SizeY(&wk->mwin[i]),
				STARTMENU_WCOL_NORMAL);
		}
	}
	// スクリーンの全体を再転送
	GF_BGL_LoadScreenReq(wk->bgl, GF_BGL_FRAME0_M);
}

//------------------------------------------------------------------
/**
 * @brief	ウィンドウの枠(フレーム)を再表示(最初からはじめる選択時の警告ウィンドウ用)
 * @param	NONE
 * @return	NONE
 */
//------------------------------------------------------------------
static void RedrawWindowFrameNewGame(STARTMENU_WORK *wk, int select)
{
	int i;
	GF_BGL_BMPWIN	*win = wk->beacon_win_sub;

	for(i = 0; i < 2; i++){
		if(GF_BGL_BmpWinAddCheck(&win[i]) == FALSE)	continue;

		if(select  < 0){	//全部無効パターン
			BmpMenuWinWrite(&win[i], WINDOW_TRANS_OFF, STARTMENU_FCHR1, STARTMENU_FCOL1);
			GF_BGL_ScrPalChange(wk->bgl, GF_BGL_FRAME1_M,
				GF_BGL_BmpWinGet_PosX(&win[i]),	GF_BGL_BmpWinGet_PosY(&win[i]),
				GF_BGL_BmpWinGet_SizeX(&win[i]), GF_BGL_BmpWinGet_SizeY(&win[i]),
				STARTMENU_WCOL_NORMAL);
		}else if(wk->key_mode == APP_KTST_TOUCH){
			BmpMenuWinWrite(&win[i], WINDOW_TRANS_OFF, STARTMENU_FCHR2, STARTMENU_FCOL1);
			GF_BGL_ScrPalChange(wk->bgl, GF_BGL_FRAME1_M,
				GF_BGL_BmpWinGet_PosX(&win[i]),	GF_BGL_BmpWinGet_PosY(&win[i]),
				GF_BGL_BmpWinGet_SizeX(&win[i]), GF_BGL_BmpWinGet_SizeY(&win[i]),
				STARTMENU_WCOL_SELECT);
		}else if(i == select){
			BmpMenuWinWrite(&win[i], WINDOW_TRANS_OFF, STARTMENU_FCHR2, STARTMENU_FCOL2);
			GF_BGL_ScrPalChange(wk->bgl, GF_BGL_FRAME1_M,
				GF_BGL_BmpWinGet_PosX(&win[i]),	GF_BGL_BmpWinGet_PosY(&win[i]),
				GF_BGL_BmpWinGet_SizeX(&win[i]), GF_BGL_BmpWinGet_SizeY(&win[i]),
				STARTMENU_WCOL_SELECT);
		} else {
			BmpMenuWinWrite(&win[i], WINDOW_TRANS_OFF, STARTMENU_FCHR1, STARTMENU_FCOL1);
			GF_BGL_ScrPalChange(wk->bgl, GF_BGL_FRAME1_M,
				GF_BGL_BmpWinGet_PosX(&win[i]),	GF_BGL_BmpWinGet_PosY(&win[i]),
				GF_BGL_BmpWinGet_SizeX(&win[i]), GF_BGL_BmpWinGet_SizeY(&win[i]),
				STARTMENU_WCOL_NORMAL);
		}
	}
	// スクリーンの全体を再転送
	GF_BGL_LoadScreenReq(wk->bgl, GF_BGL_FRAME1_M);
}


//------------------------------------------------------------------
/**
 * @brief	次のカーソル位置を検索する
 * @param	NONE
 * @return	NONE
 */
//------------------------------------------------------------------
static BOOL NextCursorPosition(STARTMENU_WORK *wk, int offset)
{
	int old = wk->cursor;
	int now = wk->cursor;

	while(1){
		now += offset;
		// オーバーフロー検査
		if(now == -1){
			now = 0;
		}
		if(now == MENU_WIN_MAX){
			now = MENU_WIN_MAX - 1;
		}
		// 動ける場所がなければ動かない
		if(now == wk->cursor){
			break;
		}
		// 動ける場所が見つかったら決定
		if(wk->menuflag[now]){
			Snd_SePlay(SEQ_SE_DP_SELECT);
			break;
		}
	}

	wk->cursor = now;
	if(wk->cursor != old){
		RedrawWindowFrame(wk, wk->cursor);
		wk->touch_wait = NEXT_TOUCH_SCROLL_WAIT;
		return TRUE;
	}
	return FALSE;
}

/**
 *	@brief	次の項目が先頭に来る座標を返す
 */
static int GetScrollPosUp(STARTMENU_WORK* wk,u8 base,u8 s_idx)
{
	int i;
	int	py,sy;

	for(i = s_idx; i >= 0;i--){
		py = (GF_BGL_BmpWinGet_PosY(&wk->mwin[i] ) - 1);
		if(py-base == 0){
			return (GF_BGL_BmpWinGet_SizeY(&wk->mwin[i] ) + 2 + base);
		}
	}
	//ここには来ないはずだが、一応
	return base;
}

//------------------------------------------------------------------
/**
 * @brief	カーソルが画面内に入るようにスクロール登録
 * @param	NONE
 * @return	NONE
 */
//------------------------------------------------------------------
static void SetCursorScroll(STARTMENU_WORK *wk,int pos)
{
	int cursory, height, basey;

	// ドット換算のカーソル位置を算出
	cursory = (GF_BGL_BmpWinGet_PosY(&wk->mwin[pos] ) - 1) * 8;
	height = (GF_BGL_BmpWinGet_SizeY(&wk->mwin[pos] ) + 2) * 8;

	// 現在のスクロール値(目的座標)
	basey = wk->target / FX32_ONE;

	// 画面の中に入っているか調査する
	if((basey > cursory) || (basey + HW_LCD_HEIGHT <= cursory)){
		wk->target = cursory*FX32_ONE;
		// 上下カーソルの表示処理
		SetCursorVisible(wk);
	}else{
		return;
	}
	if(wk->target == SCR_TARGET_PAGE2){
		GF_BGL_ScrFill(wk->bgl,GF_BGL_FRAME0_M,0x0000,0,0,32,12,0);
		GF_BGL_ScrFill(wk->bgl,GF_BGL_FRAME2_M,0x0000,0,0,32,12,0);
		GF_BGL_LoadScreenV_Req( wk->bgl, GF_BGL_FRAME0_M );
		GF_BGL_LoadScreenV_Req( wk->bgl, GF_BGL_FRAME2_M );
	}else if(wk->target == SCR_TARGET_PAGE0){
		CreateStartMenu(wk);
	}
}


//------------------------------------------------------------------
/**
 * @brief	上下カーソルの表示／非表示処理
 * @param	NONE
 * @return	NONE
 */
//------------------------------------------------------------------
static void SetCursorVisible(STARTMENU_WORK *wk)
{
	int i, du, dd;
	int cursory, height, basey;

	du = dd = FALSE;

	// 現在のスクロール値(目的座標)
	basey = wk->target / FX32_ONE;

	for(i = 0; i < MENU_WIN_MAX; i++){
		if(GF_BGL_BmpWinAddCheck(&wk->mwin[i]) == FALSE)
			continue;

		// ドット換算のカーソル位置を算出
		cursory = (GF_BGL_BmpWinGet_PosY(&wk->mwin[i] ) - 1) * 8;
		height = (GF_BGL_BmpWinGet_SizeY(&wk->mwin[i] ) + 2) * 8;

		// 上のはみ出しチェック
		if(basey > cursory){
			du = TRUE;
		}
		// 下のはみ出しチェック
		if(basey + HW_LCD_HEIGHT <= cursory){
			dd = TRUE;
		}
	}
	CLACT_AnmChg(wk->clcursor[0], du*2);
	CLACT_SetAnmFlag(wk->clcursor[0], 0);
	CLACT_AnmChg(wk->clcursor[1], dd*2+1);
	CLACT_SetAnmFlag(wk->clcursor[1], 0);
}


//------------------------------------------------------------------
/**
 * @brief	処理の終了 メモリ開放など
 * @param	NONE
 * @return	NONE
 */
//------------------------------------------------------------------
static void StartMenuFinish(PROC *proc)
{
	int i;
	STARTMENU_WORK *wk = PROC_GetWork(proc);

	// アクター関連の開放
	if(wk->clcursor[0] || wk->clcursor[1]){
		CLACT_Delete(wk->clcursor[0]);
		CLACT_Delete(wk->clcursor[1]);
		MysteryLib_RemoveClact();
	}

	// ウィンドウ開放
	for(i = 0; i < MENU_WIN_MAX; i++){
		if(wk->mwin[i].ini){
			GF_BGL_BmpWinOff(&wk->mwin[i]);
			GF_BGL_BmpWinDel(&wk->mwin[i]);
		}
	}
	// BGL開放
	GF_BGL_BGControlExit(wk->bgl, GF_BGL_FRAME0_M);
	GF_BGL_BGControlExit(wk->bgl, GF_BGL_FRAME1_M);
	GF_BGL_BGControlExit(wk->bgl, GF_BGL_FRAME2_M);

	//上画面をメイン,下画面をサブに戻す
	GX_SetDispSelect(GX_DISP_SELECT_MAIN_SUB);

	sys_FreeMemoryEz(wk->bgl);
	sys_VBlankFuncChange(NULL, NULL);
}


//------------------------------------------------------------------
/**
 * @brief	選択ウィンドウのパレットアニメ
 * @param	NONE
 * @return	NONE
 */
//------------------------------------------------------------------
u16 animtable[] = {
	RGB( 1, 28, 20),	RGB( 3, 28, 20),	RGB( 5, 28, 20),	RGB( 7, 28, 20),
	RGB( 9, 28, 20),	RGB(11, 28, 20),	RGB(13, 28, 20),	RGB(15, 28, 20),
	RGB(17, 28, 20),	RGB(19, 28, 20),	RGB(21, 28, 20),	RGB(23, 28, 20),
	RGB(25, 28, 20),	RGB(27, 28, 20),	RGB(29, 28, 20),	RGB(31, 28, 20),
	RGB(29, 28, 20),	RGB(27, 28, 20),	RGB(25, 28, 20),	RGB(23, 28, 20),
	RGB(21, 28, 20),	RGB(19, 28, 20),	RGB(17, 28, 20),	RGB(15, 28, 20),
	RGB(13, 28, 20),	RGB(11, 28, 20),	RGB( 9, 28, 20),	RGB( 7, 28, 20),
	RGB( 5, 28, 20),	RGB( 3, 28, 20),
	0,
};
static void SelectPalAnim(STARTMENU_WORK *wk)
{
	u16 *col = (u16 *)0x0500006C;
	if(animtable[wk->anim_index] == 0)
		wk->anim_index = 0;
	*col = animtable[wk->anim_index++];
}

static void VBlankFunc(void *work)
{
	// セルアクターVram転送マネージャー実行
	DoVramTransferManager();
	// レンダラ共有OAMマネージャVram転送
	REND_OAMTrans();
	GF_BGL_VBlankFunc( (GF_BGL_INI*)work );
	OS_SetIrqCheckFlag( OS_IE_V_BLANK );
}


//--------------------------------------------------------------------------------------------
/**
 * @brief	タイトルプロセス：初期化
 * @param	proc	プロセスへのポインタ
 * @param	seq		シーケンス用ワークへのポインタ
 * @return	PROC_RES_CONTINUE	動作継続中
 * @return	PROC_RES_FINISH		動作終了
 */
//--------------------------------------------------------------------------------------------
static PROC_RESULT StartMenuProc_Init(PROC * proc, int * seq)
{
	STARTMENU_WORK *wk;

	sys_CreateHeap( HEAPID_BASE_APP, HEAPID_STARTMENU, 0x40000);
	//	sys_PrintHeapFreeSize(HEAPID_STARTMENU);
	wk = PROC_AllocWork(proc, sizeof(STARTMENU_WORK), HEAPID_STARTMENU);
	// 初期化不良が怖いのでワークはゼロクリア
	memset(wk, 0, sizeof(STARTMENU_WORK));

	/* 各種変数の初期化 */
	wk->bgl = GF_BGL_BglIniAlloc(HEAPID_STARTMENU);

	/* 画面の初期設定 */
	WIPE_SetBrightness( WIPE_DISP_MAIN, WIPE_FADE_BLACK );
	WIPE_SetBrightness( WIPE_DISP_SUB, WIPE_FADE_BLACK );

	/* 変数初期化 */
	wk->sv = ((MAINWORK *)PROC_GetParentWork(proc))->savedata;
	wk->fdata = SaveData_GetFushigiData(wk->sv);
	//	wk->cursor = 0;
	wk->scrolly = FX32_ONE * 0;
	wk->target	= FX32_ONE * 0;

	wk->mst = SaveData_GetMyStatus(wk->sv);
	wk->zw = SaveData_GetZukanWork(wk->sv);
	wk->ptime = SaveData_GetPlayTime(wk->sv);

	wk->zukangetflag = ZukanWork_GetZukanGetFlag(wk->zw);
	wk->badgecount = MyStatus_GetBadgeCount(wk->mst);
	wk->beacon_msg_seq = BEACON_MSGSEQ_NOP;

	// ライブラリ初期化
	MysteryLib_Init(HEAPID_STARTMENU);

	// セーブデータが無ければスタートメニュー自体を表示させない
	if(!SaveData_GetExistFlag(wk->sv)){
		wk->pass_start_menu = TRUE;
	}

	Snd_BgmChannelSetAndReverbSet( 0 );	// 使用可能チャンネル操作、リバーブ設定(クリア)
	Snd_SceneSet( SND_SCENE_DUMMY );		// 次のシーンが必ず読み込まれるようにしておく！

#ifdef DEBUG_ONLY_FOR_mituhara
	OS_TPrintf("sizeof(POKEMON_PARAM) = %d\n", PokemonParam_GetWorkSize());
	OS_TPrintf("sizeof(_SEND_FLAG) = %d\n", CommPlayerNowFlagDataArraySize());
	OS_TPrintf("sizeof(MYSTATUS) = %d\n", MyStatus_GetWorkSize());
#endif

#ifdef CREATE_INDEX
	CreateIndexData(HEAPID_STARTMENU);
#endif


	return PROC_RES_FINISH;
}



//--------------------------------------------------------------------------------------------
/**
 * @brief	タイトルプロセス：メイン
 * @param	proc	プロセスへのポインタ
 * @param	seq		シーケンス用ワークへのポインタ
 * @return	PROC_RES_CONTINUE	動作継続中
 * @return	PROC_RES_FINISH		動作終了
 */
//--------------------------------------------------------------------------------------------
static PROC_RESULT StartMenuProc_Main(PROC * proc, int * seq)
{
	int ret;
	STARTMENU_WORK *wk = PROC_GetWork(proc);
	wk->jiffy++;
	CTRDG_IsExisting();

	// ビーコン受信時のメッセージ表示シーケンス
	if(BeaconMessage_Proc(wk) == TRUE){
		StartMenuBeacon_Proc(wk);
		StartMenuProc(wk);
		return PROC_RES_CONTINUE;
	}
	// 選択されているウィンドウをパレットアニメーション
	SelectPalAnim(wk);

	// タッチスクロール入力ウェイト
	if( wk->touch_wait != 0 ){
		wk->touch_wait--;
	}

	switch(*seq){
	case STARTMENU_SEQ_INIT:
		// ＢＧ関係の必要最低限の初期化
		InitStartMenuScreen(wk);
		SetSeq(*seq, STARTMENU_SEQ_CHECK_SYSTEM);
		break;

	case STARTMENU_SEQ_CHECK_SYSTEM:
		// 各種システムのチェック(一気にチェック、順次表示)
		if(StartMenuCheckSystem(wk) == 0){
			SetSeq(*seq, STARTMENU_SEQ_HARDINIT);
		} else {
			MysteryLib_RequestFade(WIPE_TYPE_FADEIN, STARTMENU_SEQ_DISP_ERROR, seq, STARTMENU_SEQ_FADE_WAIT);
			*((u16 *)HW_BG_PLTT +	0) = RGB(12, 12, 31);
		}
		break;

	case STARTMENU_SEQ_DISP_ERROR:
		// エラーがあったので詳細を表示しまくり
		if(StartMenuDisplayError(wk) == FALSE)
			MysteryLib_RequestFade(WIPE_TYPE_FADEOUT, STARTMENU_SEQ_HARDINIT, seq, STARTMENU_SEQ_FADE_WAIT);
		break;

	case STARTMENU_SEQ_HARDINIT:
		wk->beacon_seq = STARTMENU_BEACON_SEQ_WAIT;
		// セーブデータがなければゲームの最初から始める
		if(wk->pass_start_menu == TRUE){
			wk->select = SEL_FIRSTGAME;
			MysteryLib_RequestFade(WIPE_TYPE_FADEOUT, STARTMENU_SEQ_SELECT_MENU, seq, STARTMENU_SEQ_FADE_WAIT);
		} else {
			// AGBカートリッジの初期化をして次のシーケンスへ
			AgbCartridgeInit(wk);
			SetSeq(*seq, STARTMENU_SEQ_CREATE_SCREEN);
		}
		break;

	case STARTMENU_SEQ_CREATE_SCREEN:
		// カーソルオブジェクトの読み込み
		StartMenuInitClact(wk);
		// ワイヤレスアイコンの読み込み
		WirelessIconInit(wk);
		sys_VBlankFuncChange(VBlankFunc, wk->bgl);

		// スクリーン作成(基本形)
		CreateStartMenu(wk);
		RedrawWindowFrame(wk, wk->cursor);
		MysteryLib_RequestFade(WIPE_TYPE_FADEIN, STARTMENU_SEQ_MAIN, seq, STARTMENU_SEQ_FADE_WAIT);
		*((u16 *)HW_BG_PLTT +	0) = RGB(12, 12, 31);
		// ビーコンの収集を開始する
		wk->beacon_seq = STARTMENU_BEACON_SEQ_INIT;
		break;

	case STARTMENU_SEQ_MAIN:
		// 決定ボタン / キャンセルボタン
		ret = InputCheckMenu(wk,seq);
		// 再描画の必要があれば再描画する
		if(wk->redrawflag == TRUE){
			CreateStartMenu(wk);
			wk->redrawflag = FALSE;
			break;
		}
		// リスクエストが出ていればポップアップメニューの登録
		if(*seq == STARTMENU_SEQ_MAIN && wk->req_popup == TRUE){
			wk->req_popup = FALSE;
			wk->beacon_msg_wait = 1;
		}

		break;

	case STARTMENU_SEQ_SELECT_FIRSTGAME:
		// さいしょからはじめるを選んだ時は警告を表示
		if(wk->beacon_msg_seq == BEACON_MSGSEQ_NOP){
			if(wk->beacon_result & PAD_BUTTON_CANCEL){
				SetSeq(*seq, STARTMENU_SEQ_MAIN);
			} else {
				MysteryLib_RequestFade(WIPE_TYPE_FADEOUT, STARTMENU_SEQ_SELECT_MENU, seq, STARTMENU_SEQ_FADE_WAIT);
			}
		}
		break;


	case STARTMENU_SEQ_SELECT_MENU:
		// メモリ群を開放
		StartMenuFinish(proc);
		return PROC_RES_FINISH;
		break;


	case STARTMENU_SEQ_FADE_WAIT:
		// フェードが終了するまで待って次のシーケンスへ
		MysteryLib_FadeEndCheck(seq);
		break;

	case STARTMENU_SEQ_FINISH:
		return PROC_RES_FINISH;
		break;
	}

	StartMenuBeacon_Proc(wk);
	StartMenuProc(wk);
	MysteryLib_DoClact();

	return PROC_RES_CONTINUE;
}



//------------------------------------------------------------------
/**
 * @brief	選択されたメニューによって処理分岐
 * @param	NONE
 * @return	NONE
 */
//------------------------------------------------------------------
#include "system/gamestart.h"
#include "demo/title.h"
#include "application/phclink.h"

FS_EXTERN_OVERLAY( title );
FS_EXTERN_OVERLAY( startmenu );
FS_EXTERN_OVERLAY( email );
FS_EXTERN_OVERLAY( phc );

extern const PROC_DATA MysteryGiftProcData;
extern const PROC_DATA AgbCartridgeProcData;
extern const PROC_DATA PokemonRangerProcData;
extern const PROC_DATA StartMenuWifiProcData;
extern const PROC_DATA EmailProcData;

static void StartMenuSetNextProc(STARTMENU_WORK *wk)
{
	switch(wk->select){
	case SEL_CONTINUE:	// つづきから　はじめる
		Main_SetNextProc(OVERLAY_ID_GAMESTART, &ContinueGameStartProcData);
		break;
	case SEL_FIRSTGAME:	// さいしょから　はじめる
		Main_SetNextProc(OVERLAY_ID_GAMESTART, &NewGameStartProcData);
		break;
	case SEL_MYSTERY:	// ふしぎな　おくりもの
		Main_SetNextProc(FS_OVERLAY_ID(startmenu), &MysteryGiftProcData);
		break;
	case SEL_AGBPOKEMON:	// ×××から　つれてくる
		Main_SetNextProc(FS_OVERLAY_ID(startmenu), &AgbCartridgeProcData);
		break;
	case SEL_RANGER:	// ポケモンレンジャーとの　せつぞく
		Main_SetNextProc(FS_OVERLAY_ID(startmenu), &PokemonRangerProcData);
		break;
	case SEL_WII:		// Wiiと　せつぞく
		rebooter(WIICLIENT_FILE);
		break;
	case SEL_WIFI:	// Wi-Fiせってい
		Snd_Stop();
		Main_SetNextProc(NO_OVERLAY_ID, &StartMenuWifiProcData);
		break;
	case SEL_PHC:	// PHC
		Snd_Stop();
		Main_SetNextProc(FS_OVERLAY_ID( phc ), &PhcLinkProcData );
		break;
	case SEL_EMAIL:	// EMAIL
		Snd_Stop();
		Main_SetNextProc(FS_OVERLAY_ID(email), &EmailProcData);
		break;
	case SEL_CANCEL:	// キャンセル
		Main_SetNextProc( FS_OVERLAY_ID(title), &TitleProcData);
		break;
	}
}

//--------------------------------------------------------------------------------------------
/**
 * @brief	タイトルプロセス：終了
 * @param	proc	プロセスへのポインタ
 * @param	seq		シーケンス用ワークへのポインタ
 * @return	PROC_RES_CONTINUE	動作継続中
 * @return	PROC_RES_FINISH		動作終了
 */
//--------------------------------------------------------------------------------------------
static PROC_RESULT StartMenuProc_End(PROC * proc, int * seq)
{
	STARTMENU_WORK *wk = PROC_GetWork(proc);

	StartMenuSetNextProc(wk);

	PROC_FreeWork(proc);
	sys_DeleteHeap(HEAPID_STARTMENU);

	/* AGBカートリッジの抜け検出OFF */
	MysteryLib_SetAgbCartridgeIntr(FALSE);

	return PROC_RES_FINISH;
}


//--------------------------------------------------------------------------------------------
// この定義はsrc/demo/title.cから参照されます
//--------------------------------------------------------------------------------------------
//FS_EXTERN_OVERLAY(startmenu);
const PROC_DATA StartMenuProcData = {
	StartMenuProc_Init,
	StartMenuProc_Main,
	StartMenuProc_End,
	NO_OVERLAY_ID,
};



/*	*/